using Viyi.Util.Extensions;

namespace Viyi.Util.DateTimes;

public static partial class DateTimeHelper {
    public static readonly IFormats DefaultFormats = InternalDefaultFormats.Instance;
    internal static readonly DateTime StartTimeInJava = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    /// <summary>
    /// 根据 Java 中表示时间和 <c>long</c> 型数据，恢复成 <see cref="DateTime" /> 类型数据。
    /// </summary>
    /// <param name="value"></param>
    /// <param name="timezone"></param>
    /// <returns></returns>
    public static DateTime FromJavaMilliseconds(long value, TimeZoneInfo? timezone = null) {
        var date1970 = TimeZoneInfo.ConvertTime(
            StartTimeInJava,
            TimeZoneInfo.Utc,
            timezone ?? TimeZoneInfo.Local
        );
        return new DateTime(date1970.Ticks + value * 10000);
    }

    /// <summary>
    /// 全局格式
    /// </summary>
    public static DefinedFormat Formats {
        get {
            return formats ??= new DefinedFormat {
                DateTime = DefaultFormats.DateTime,
                Date = DefaultFormats.Date,
                Time = DefaultFormats.Time
            };
        }
        set { formats = value; }
    }
    private static DefinedFormat? formats;

    public static void SetFormats(IFormats formats, bool ignoreEmpty = true) {
        if (formats == null) { return; }
        var globalFormats = Formats;
        formats.DateTime.IfNot(check, it => globalFormats.DateTime = it);
        formats.Date.IfNot(check, it => globalFormats.Date = it);
        formats.Time.IfNot(check, it => globalFormats.Time = it);

        bool check(string? value) => ignoreEmpty && string.IsNullOrWhiteSpace(value);
    }


    private sealed class InternalDefaultFormats : IFormats {
        public static readonly InternalDefaultFormats Instance;
        static InternalDefaultFormats() {
            Instance = new InternalDefaultFormats();
        }

        public string? DateTime => "yyyy-MM-dd HH:mm:ss";
        public string? Date => "yyyy-MM-dd";
        public string? Time => "HH:mm:ss";
    }
}
